/*
 * $Id: sysapi_getpnm.c,v 1.5 2005-11-01 16:18:12 bacon Exp $
 */

#include <xp/bas/sysapi.h>
#include <xp/bas/string.h>
#include <xp/bas/mstring.h>
#include <xp/bas/memory.h>
#include <xp/bas/locale.h>

/*
#ifndef _WIN32
static void __trim_unix_path (xp_char_t* pp);
#endif
*/

int xp_getpnm (const xp_char_t* argv0, xp_char_t* buf, xp_size_t size)
{
#ifdef _WIN32
	if (GetModuleFileName (XP_NULL, buf, size) == 0) return -1;
#else
	if (argv0 == XP_NULL) return -1;

	if (argv0[0] == XP_CHAR('/')) {
		/*xp_strxcpy (buf, size, argv0);*/
		if (xp_trimpath(argv0, buf, size) == (xp_size_t)-1) return -1;
	}
	else if (xp_strchr(argv0, XP_CHAR('/'))) {
		if (xp_getcwd (buf, size) == -1) return -1;
		xp_strxcap (buf, size, XP_TEXT("/"), argv0, XP_NULL);
		/*__trim_unix_path (buf);*/
		xp_trimpath (buf, buf, size);
	}
	else {
		xp_char_t *p, *q, * px = XP_NULL;
		xp_stat_t st;
		xp_char_t dir[XP_PATH_MAX + 1];
		xp_char_t pbuf[XP_PATH_MAX + 1];
		int first = 1;

#ifdef XP_CHAR_IS_MCHAR
		p = getenv("PATH");
		if (p == XP_NULL) p = (xp_char_t*)XP_TEXT("/bin:/usr/bin");
#else
		xp_mchar_t* mp = getenv ("PATH");

		if (mp == XP_NULL) p = (xp_char_t*)XP_TEXT("/bin:/usr/bin");
		else {
			xp_size_t mplen = xp_mstrlen(mp), n;

			px = (xp_char_t*) xp_malloc (
				xp_sizeof(xp_wchar_t) * (mplen + 1));
			if (px == XP_NULL) return -1;

			n = xp_mcstowcs (mp, px, mplen + 1);
			if (n == (xp_size_t)-1 || n < mplen) {
				xp_free (px);
				return -1;
			}

			p = px;
		}
#endif

		for (;;) {
			while (*p == XP_CHAR(':')) p++;
			if (*p == XP_CHAR('\0')) {
				if (first) {
					p = (xp_char_t*)XP_TEXT("./");
					first = 0;
				}
				else {
					if (px != XP_NULL) xp_free (px);
					return -1;
				}
			}

			q = p;
			while (*p != XP_CHAR(':') && *p != XP_CHAR('\0')) p++;

			if (p - q >= xp_countof(dir) - 1) {
				if (px != XP_NULL) xp_free (px);
				return -1;
			}

			xp_strxncpy (dir, xp_countof(dir), q, p - q);
			/*__trim_unix_path (dir);*/
			xp_trimpath (dir, dir, xp_countof(dir));

			xp_strxapp (pbuf, xp_countof(pbuf), dir, XP_TEXT("/"), argv0, XP_NULL);

			if (xp_access(pbuf, XP_ACCESS_EXECUTE) == 0 && 
			    xp_stat(pbuf, &st) == 0 && S_ISREG(st.st_mode)) {
				break;
			}
		}

		if (px != XP_NULL) xp_free (px);

		if (pbuf[0] == XP_CHAR('/')) xp_strxcpy (buf, size, pbuf);
		else {
			if (xp_getcwd (buf, size) == -1) return -1;
			xp_strxcap (buf, size, XP_TEXT("/"), pbuf, XP_NULL);
			/*__trim_unix_path (buf);*/
			xp_trimpath (buf, buf, size);
		}
	}
#endif	
	return 0;
}

#if 0

#ifndef _WIN32
static void __trim_unix_path (xp_char_t* pp)
{
	xp_char_t* p, * q; 

	for (p = pp; p[0]; p++) {
		if (p[0] == XP_CHAR('/')) {
			if (p[1] == XP_CHAR('/')) {
				for (q = p; q[0] == XP_CHAR('/'); q++) ;
				xp_strcpy (&p[1], q); p--;
			}
			else if ((p[1] == XP_CHAR('.') && p[2] == XP_CHAR('.')) &&
			         (p[3] == XP_CHAR('/') || p[3] == XP_CHAR('\0'))) {
				if (p == pp && p[0] == XP_CHAR('/')) {
					xp_strcpy (p, &p[3]);
					if (*pp == XP_CHAR('\0')) 
						xp_strcpy (pp, XP_TEXT("/"));
				}
				else {
					for (q = p - 1; q >= pp && *q != XP_CHAR('/'); q--) ;

					if (q[0] == XP_CHAR('/') && 
					    xp_strcmpn(q, XP_TEXT("/../"), 4) &&
					    !(&q[-1] > pp && q[-1] == XP_CHAR('/'))) {

						xp_strcpy (q, &p[3]);
						if (*pp == XP_CHAR('\0'))
							xp_strcpy (pp, XP_TEXT("/"));
						p = q - 1;
					}
				}
			}
			/*
			 *    /etc/./magic ---> /etc/magic
			 */
			else if (p[1] == XP_CHAR('.')) {
				if (p == pp) {
					if (p[2] == XP_CHAR('/')) {
						xp_strcpy (p, &p[2]); p--;
					}
					else if (p[2] == XP_CHAR('\0')) {
						p[1] = XP_CHAR('\0');
						break;
					}
				}
				else {
					if (p[2] == XP_CHAR('/') || p[2] == XP_CHAR('\0')) {
						xp_strcpy (p, &p[2]); p--;
					}
				}
			}
			else if (p != pp && p[1] == XP_CHAR('\0')) {
				*p = XP_CHAR('\0');
				break;
			}
		}
	}
}
#endif

#endif
